﻿#include "Contra.h"


CContra::CContra()
{
	_isRight = true;
	_isJump = true;
	_isMove = true;
	_isDown = 0;
	_dwFallTime = 0;
	_dwStartFall = 0;
	frame_start = GetTickCount();
	tick_per_frame = TIMESTART;
	_isSwim = false;
	//gun
	_gun = false;
	_tick_per_gun = 700;
	_tick_bullet = 300;
	_bullet_start = GetTickCount();
	_levelBullet = 4;
}

int CContra::ContraLoadSound(Sound isound)
{
	_sound = isound;
	
	_CSound = _sound.LoadSound(L"resources\\Sound\\Bullet_Contra_01.wav");
	if (_CSound == NULL)
		return 0;

	return 1;
}

void CContra::LoadResource(LPDIRECT3DDEVICE9 d3ddv, LPD3DXSPRITE &SpriteHandler, HINSTANCE hInstance, HWND hWnd)
{
	_vectorX = 0.0f;
	_vectorY = 0.0f;
	_gun = true;

	_rSprite = new CSprite(SpriteHandler, L"resources\\contraright.png", CONTRAWIDTH, CONTRAHEIGHT, 40, 10, D3DCOLOR_XRGB(255, 255, 255));
	_lSprite = new CSprite(SpriteHandler, L"resources\\contraleft.png", CONTRAWIDTH, CONTRAHEIGHT, 40, 10, D3DCOLOR_XRGB(255, 255, 255));
	_bossLight = new CSprite(SpriteHandler, L"resources\\bosslight1.png", FRAMEWIDTH, FRAMEHEIGHT, 3, 3, D3DCOLOR_XRGB(255, 255, 255));

	_sprite_bullet = new CSprite(SpriteHandler, L"resources\\bullet.png", 28, 28, 11, 11, D3DCOLOR_XRGB(255, 255, 0));

	_x = FRAMEWIDTH + FRAMEWIDTH / 2;
	//_x = MARK5;
	#pragma region DANG

	if (_x < LIMIT_SWIM_X)
		_groundY = LIMIT_SWIM_Y;
	else
		_groundY = LIMIT_Y;
	
	_y = GROUNDY + FRAMEHEIGHT * 2;

	#pragma endregion

	_rSprite->Next(10, 4);
	
	InitKeyboard(hInstance, hWnd);
}

void CContra::ProcessInput()
{
	if (_isJump || !_isFall || (_isFall && _dwFallTime > FALL_DELAY_TIME))
	{
		_isDown = 0;
		if (IsKeyDown(DIK_S))
		{
			_isDown = 1;

		}
		else
		{
			if (IsKeyDown(DIK_W))
				_isDown = -1;
		}

		if (IsKeyDown(DIK_D))
		{
			if (_isSwim && _isDown == 1)
			{
				_vectorX = 0.0f;
			}
			else
			{
				_vectorX = MOVING_SPEED;
				_isRight = true;
				_isMove = true;
			}
		}
		else
		{
			if (IsKeyDown(DIK_A))
			{
				if (_isSwim && _isDown == 1)
				{
					_vectorX = 0.0f;
				}
				else
				{
					_vectorX = -MOVING_SPEED;
					_isRight = false;
					_isMove = true;
				}
			}
			else
			{
				if (!_isJump)
				{
					_vectorX = 0.0f;
					_isMove = false;
				}
			}
		}
		
	}

	//test bullet
	if (IsKeyDown(DIK_0))
		_levelBullet = 0;
	if (IsKeyDown(DIK_1))
		_levelBullet = 1;
	if (IsKeyDown(DIK_2))
		_levelBullet = 2;
	if (IsKeyDown(DIK_3))
		_levelBullet = 3;
	if (IsKeyDown(DIK_4))
		_levelBullet = 4;
	if (IsKeyDown(DIK_5))
		_levelBullet = 5;
	if (IsKeyDown(DIK_6))
		_levelBullet = 6;
	if (IsKeyDown(DIK_7))
		_levelBullet = 7;
	if (IsKeyDown(DIK_8))
		_levelBullet = 8;
	if (IsKeyDown(DIK_9))
		_levelBullet = 9;
	if (IsKeyDown(DIK_P))
		_levelBullet = 10;
}

void CContra::ContraGun()
{
	_gun = true;

	if (_levelBullet != 4)
	{
		_sprite_bullet->Next(_levelBullet, 1);
	}
	else
	{
		_sprite_bullet->Next(_levelBullet - 1, 3);
	}

	_gunContra.GunContra_Run(_isJump, _isRight, _isDown, _isMove, _levelBullet, _x, _y, _rSprite, _lSprite);
}

void CContra::OnKeyDown(int KeyCode)
{
	switch (KeyCode)
	{
	case DIK_L:
		#pragma region DANG

		if (!_isSwim && _y == _groundY)
		{
			if (!_isMove && _isDown == 1)
			{
				if (_x < LIMIT_SWIM_X)
				{
					_groundY = LIMIT_SWIM_Y - 1;
					_isFall = true;
					_y -= 38;
				}
				else
				{
					int indexHeight = _y / FRAMEHEIGHT;
					int indexWidth = (_x + FRAMEWIDTH / 2) / FRAMEWIDTH;
					int groundY = FindLandToStand(indexHeight - 1, indexWidth);
					
					if (groundY > LIMIT_Y)
					{
						_groundY = groundY - 1;
						_isFall = true;
						_y -= 38;
					}
				}
			}
			else
			{
				_vectorY += JUMP_VELOCITY_BOOST;			// start jump if is not "on-air"j
				_isJump = true;
			}
		}
		#pragma endregion

		break;
	case DIK_J:
		if (GetTickCount() - _bullet_start > _tick_bullet)
		{
			_bullet_start = GetTickCount();
			ContraGun();
		}

		_sound.PlaySound(_CSound);
		break;
	}
}

void CContra::Contra_Run()
{
	ProcessKeyBoard();
	ProcessInput();

	#pragma region DANG
	_lastY = _y;
	#pragma endregion

	_x += _vectorX;
	_y -= _vectorY;

	vpx = _x - SCREEN_WIDTH / 2;
	vpy = SCREEN_HEIGHT;
	if (vpx <= 0)
	{
		vpx = 0;
		_x -= _vectorX / 4;
	}
	if (vpx >= GAMEWORLDWIDTH - SCREEN_WIDTH)
	{
		vpx = GAMEWORLDWIDTH - SCREEN_WIDTH;
		_x -= _vectorX / 4;
	}

	if (_x >= GAMEWORLDWIDTH - FRAMEWIDTH - 100)
	{
		_x = GAMEWORLDWIDTH - FRAMEWIDTH - 100;
	}
	if (_x <= 0)
	{
		_x = 0;
	}

	#pragma region DANG

	if (!_isJump && _isFall)
	{
		if (_dwStartFall == 0)
			StartFall();
		else
			ProcessFall();
	}

	if (_y > _groundY)
	{
		_vectorY -= FALLDOWN_VELOCITY_DECREASE;
	}
	else
	{
		_y = _groundY;
		_vectorY = 0;
		_isJump = false;
		
		EndFall();
		_isFall = false;
	}

	if (_x < LIMIT_SWIM_X && _y <= LIMIT_SWIM_Y && !_isOnLand)
	{
		_isSwim = true;
		_isJump = false;

		EndFall();
		_isFall = false;
	}

	
	#pragma endregion
}

void CContra::Update()
{
	#pragma region DANG 

	/*if (_isRight)
	{
	if (_isJump)
	{
	_rSprite->Next(10, 4);
	}
	else
	{
	if (_isMove)
	{
	if (_isDown == 1)
	{
	_rSprite->Next(23, 3);
	}
	else
	{
	if (_isDown == -1)
	{
	_rSprite->Next(20, 3);
	}
	else
	{
	_rSprite->Next(0, 5);
	}
	}
	}
	else
	{
	if (_isDown == 1)
	{
	_rSprite->Next(7, 1);
	}
	else
	{
	if (_isDown == -1)
	{
	_rSprite->Next(8, 1);
	}
	else
	{
	_rSprite->Next(5, 1);
	}
	}
	}
	}
	}
	else
	{
	if (_isJump)
	{
	_lSprite->Next(16, 4);
	}
	else
	{
	if (_isMove)
	{
	if (_isDown == 1)
	{
	_lSprite->Next(24, 3);
	}
	else
	{
	if (_isDown == -1)
	{
	_lSprite->Next(27, 3);
	}
	else
	{
	_lSprite->Next(5, 5);
	}
	}
	}
	else
	{
	if (_isDown == 1)
	{
	_lSprite->Next(2, 1);
	}
	else
	{
	if (_isDown == -1)
	{
	_lSprite->Next(0, 1);
	}
	else
	{
	_lSprite->Next(4, 1);
	}
	}
	}
	}
	}*/
	//if (_gun == false)
	{
		if (_isRight)
		{
			if (_isJump)
			{
				_rSprite->Next(10, 4);
			}
			else if (_isFall)
			{
				_rSprite->Next(3, 1);
			}
			else if (_isSwim)
			{
				if (_isDown == 1)
					_rSprite->Next(28, 1);
				else
					_rSprite->Next(26, 1);
			}
			else
			{
				if (_isMove)
				{
					if (_isDown == 1)
					{
						_rSprite->Next(23, 3);
					}
					else
					{
						if (_isDown == -1)
						{
							_rSprite->Next(20, 3);
						}
						else
						{
							if (_gun)
								_rSprite->Next(30, 5);
							else
							_rSprite->Next(0, 5);
						}
					}
				}
				else
				{
					if (_isDown == 1)
					{
						_rSprite->Next(7, 1);
					}
					else
					{
						if (_isDown == -1)
						{
							_rSprite->Next(8, 1);
						}
						else
						{
							_rSprite->Next(5, 1);
						}
					}
				}
			}
		}
		else
		{
			if (_isJump)
			{
				_lSprite->Next(16, 4);
			}
			else if (_isFall)
			{
				_lSprite->Next(5, 1);
			}
			else if (_isSwim)
			{
				if (_isDown == 1)
					_lSprite->Next(21, 1);
				else
					_lSprite->Next(23, 1);
			}
			else
			{
				if (_isMove)
				{
					if (_isDown == 1)
					{
						_lSprite->Next(24, 3);
					}
					else
					{
						if (_isDown == -1)
						{
							_lSprite->Next(27, 3);
						}
						else
						{
							if (_gun)
								_lSprite->Next(35, 5);
							else
								_lSprite->Next(5, 5);
						}
					}
				}
				else
				{
					if (_isDown == 1)
					{
						_lSprite->Next(2, 1);
					}
					else
					{
						if (_isDown == -1)
						{
							_lSprite->Next(0, 1);
						}
						else
						{
							_lSprite->Next(4, 1);
						}
					}
				}
			}
		}
	}
	
	#pragma endregion
}

void CContra::Render()
{
	DWORD now = GetTickCount();
	if (now - frame_start >= tick_per_frame)
	{
		frame_start = now;
		Update();
		_bossLight->Next();		
	}

	CCamera::getInstance()->Update(_x, _y);

	// light on the boss1
	if (_x >= GAMEWORLDWIDTH - SCREEN_WIDTH)
		_bossLight->Render(FRAMEWIDTH / 2 + FRAMEWIDTH * 100 + FRAMEWIDTH / 2 + 5, FRAMEHEIGHT + FRAMEHEIGHT / 2 + FRAMEHEIGHT - FRAMEHEIGHT / 2);

	//render contra
	if (_isRight)
	{
		_rSprite->Render(FRAMEWIDTH / 2 + _x, _y - FRAMEHEIGHT / 2);
	}
	else
	{
		_lSprite->Render(FRAMEWIDTH / 2 + _x, _y - FRAMEHEIGHT / 2);
	}

	//bullet
	//if (_gun == true)
	{
		_gunContra.Draw(_sprite_bullet);
		if (_gun)
		{
			if (now - _gun_start >= _tick_per_gun)
			{
				_gun_start = now;
				_gun = false;
			}
		}
	}

}

void CContra::Contra_End()
{
	if (_rSprite != NULL)
		delete _rSprite;

	if (_lSprite != NULL)
		delete _lSprite;

	if (_fSprite != NULL)
		delete _fSprite;

	if (_bossLight != NULL)
		delete _bossLight;

	if (_CSound != NULL)
		delete _CSound;

	_gunContra.GunContra_End();
}

CContra::~CContra()
{
}

#pragma region DANG

void CContra::HandleCollisionOnMap()
{
	//box la rectangle cua contra
	//block la rectangle cua doi tuong
	Box box, block;

	//bien xac dinh doi tuong muon xet co dung duoc khong
	bool isStand;

	//tile number hien tai
	int tileNumber;

	//index dung de xet vi tri tren map
	int indexWidth, indexHeight;

	//bien dung de xac dinh mat va cham
	float normalx, normaly;

	//neu con tra khong o trang thai boi
	if (!_isSwim)
	{
	#pragma region NOT SWIM
		indexHeight = _y / FRAMEHEIGHT;

		indexWidth = (_x + FRAMEWIDTH / 2) / FRAMEWIDTH;

		//xet vi tri duoi chan contra
		isStand = _collisionMap.GetMapStatus(indexHeight, indexWidth);

		//
		tileNumber = _collisionMap.GetTileNumber(indexHeight, indexWidth);

		//truong hop vi tri o MAP[indexHeight][indexWidth] co the dung
		if (isStand)
		{
			//lay rectangle contra xet va cham
			box = GetBox();

			//vi tri
			if (tileNumber != 37)
				block.SetPosition(indexWidth * FRAMEWIDTH, indexHeight * FRAMEHEIGHT);
			else
				block.SetPosition(indexWidth * FRAMEWIDTH, (indexHeight - 0.5) * FRAMEHEIGHT);

			//phan co? chi co kich thuoc 32
			block.SetContent(FRAMEWIDTH, 32);

			//van toc
			block.SetVelocity(0, 0);

			//neu contra dang chuyen dong tu tren xuong
			if (_lastY > _y)
			{
			#pragma region CHUYEN DONG TU TREN XUONG

				if (box.fVy > 0)
					box.iY -= FRAMEHEIGHT / 2;
				if (box.fVy < 0)
					box.iY += FRAMEHEIGHT / 2;

				//chi xet va cham neu ground thay doi
				if (_groundY != block.iY + FRAMEHEIGHT)
				{
					//neu va cham
					if (isCollide(box, block, normalx, normaly))
					{
						//neu mat va cham la bottom
						if (normalx == 0 && normaly == 1)
						{
							_groundY = block.iY + FRAMEHEIGHT - 1;
							_isFall = false;
							_isSwim = false;
							_isOnLand = true;
							_lastTileNumber = tileNumber;
						}
					}
				}
			#pragma endregion
			}
			else if (_lastY == _y)
			{
			#pragma region CHUYEN DONG NGANG
				// co 2 loai
				if ((_lastTileNumber != 37 && tileNumber == 37) || (_lastTileNumber == 37 && tileNumber != 37))
				{
					if (_x < LIMIT_SWIM_X)
						_groundY = LIMIT_SWIM_Y - 1;
					else
						_groundY = LIMIT_Y - 1;
				}
			#pragma endregion
			}
		}
		//truong hop vi tri o MAP[indexHeight][indexWidth] khong the dung
		else
		{
			//tinh gioi han roi
			int limit;
			if (_x < LIMIT_SWIM_X)
				limit = LIMIT_SWIM_Y;
			else
				limit = LIMIT_Y;
			if (_lastY >= _y)
			{
			#pragma region CHUYEN DONG TU TREN XUONG VA CHUYEN DONG NGANG

				if (_groundY > limit - 1)
				{
					_groundY = limit - 1;
					_isFall = true;
					_isSwim = false;

					//neu ben duoi co the dung duoc thi thiet lap _isOnLand = true
					if (_collisionMap.GetMapStatus(1, indexWidth))
						_isOnLand = true;
					else
						_isOnLand = false;
					//co truong hop jump nhung _groundY > limit nen khong the thiet lap _isJump ve false
				}
				else if (_groundY == limit - 1)
				{
					//truong hop nay dung khi contra dang boi hoac dang dung o vien da sat mat nuoc
					if (_y == limit - 1 && limit == LIMIT_SWIM_Y)
					{
						_isSwim = true;
						_isFall = false;
						_isJump = false;
						_isOnLand = false;
					}
				}
			#pragma endregion
			}
		}
#pragma endregion
	}

	//neu contra dang boi
	else
	{
	#pragma region SWIM
		indexHeight = _y / FRAMEHEIGHT;

		indexWidth = _x / FRAMEWIDTH;

		//contra huong ben phai
		if (_isRight)
			isStand = _collisionMap.GetMapStatus(indexHeight, indexWidth + 1);
		//contra huong ben trai
		else
			isStand = _collisionMap.GetMapStatus(indexHeight, indexWidth - 1);

		//neu cho contra sap boi toi co the dung duoc
		if (isStand)
		{
			//lay rectangle de xet va cham
			box = GetBox();

			block.iY = indexHeight * FRAMEHEIGHT;
			block.SetContent(FRAMEWIDTH, FRAMEHEIGHT / 2);

			block.SetVelocity(0, 0);

			if (_isRight)
			{
			#pragma region HUONG BEN PHAI
				//truyen vao vi tri cua contra tru di do lon cua no
				block.iX = (indexWidth + 1) * FRAMEWIDTH;

				//neu co va cham
				if (isCollide(box, block, normalx, normaly))
				{
					//neu mat va cham la mat phai
					if (normaly == 0 && normalx == 1)
					{
						//thiet lap groundy
						_groundY = LIMIT_SWIM_Y - 1;

						//thiet lap trang thai boi ve false
						_isSwim = false;

						//thiet lap trang thai dung tren dat ve true
						_isOnLand = true;
					}
				}
			#pragma endregion
			}

			else
			{
			#pragma region HUONG BEN TRAI
				///do contra nam ben phai doi tuong nen truyen vao vi tri cua contra tru di do rong cua no
				//vi lay index dua vao vi tri goc trai cua contra
				box.iX -= box.iWidth;
				block.iX = (indexWidth - 1) * FRAMEWIDTH;

				if (isCollide(box, block, normalx, normaly))
				{
					//neu mat va cham la mat trai
					if (normaly == 0 && normalx == -1)
					{
						//thiet lap groundy
						_groundY  = LIMIT_SWIM_Y - 1;

						//thiet lap trang thai boi ve false
						_isSwim = false;

						//thiet lap trang thai dung tren dat ve true
						_isOnLand = true;
					}
				}
			#pragma endregion
			}
		}
	#pragma endregion
	}
}

int CContra::FindLandToStand(int indexHeight, int indexWidth)
{
	//both tile number 25 and 37 are land where contra can stand on
	int land1 = _collisionMap.FindTileNumber(indexHeight, indexWidth, 25);
	int land2 = _collisionMap.FindTileNumber(indexHeight, indexWidth, 37);

	if (land1 == -1 && land2 == -1)
		return LIMIT_Y;
	else if (land1 != -1 && land2 != -1)
	{
		if (land1 > land2)
			return land1 * FRAMEHEIGHT;
		else
			return (land2 - 0.5) * FRAMEHEIGHT;
	}
	else
	{
		if (land1 != -1)
			return land1 * FRAMEHEIGHT;
		else
			return (land2 - 0.5) * FRAMEHEIGHT;
	}
}

Box CContra::GetBox()
{
	Box box;

	if (_isJump)
	{
		box.iY = _y - 54;
		box.iX = _x + 15;
		box.iHeight = 42;
		box.iWidth = 40;
	}
	else if (_isFall)
	{
		box.iY = _y - 24;
		box.iX = _x + 11;
		box.iHeight = 72;
		box.iWidth = 48;
	}
	else if (_isSwim)
	{
		box.iY = _y - 64;
		box.iX = _x + 11;
		box.iHeight = 32;
		box.iWidth = 48;
	}
	else
	{
		if (_isMove)
		{
			box.iY = _y - 24;
			box.iX = _x + 11;
			box.iHeight = 72;
			box.iWidth = 48;
		}
		else
		{
			if (_isDown == 1)
			{
				box.iY = _y - 62;
				box.iX = _x;
				box.iHeight = 34;
				box.iWidth = 70;
			}
			else
			{
				if (_isDown == -1)
				{
					box.iY = _y;
					box.iX = _x + 15;
					box.iHeight = 92;
					box.iWidth = 32;
				}
				else
				{
					box.iY = _y - 24;
					box.iX = _x + 11;
					box.iHeight = 72;
					box.iWidth = 48;
				}
			}
		}
	}


	box.SetVelocity(_vectorX, _vectorY);
	return box;
}

void CContra::StartFall()
{
	_dwStartFall= GetTickCount();
	_dwFallTime = 0;
}

void CContra::ProcessFall()
{
	DWORD now = GetTickCount();
	_dwFallTime = now - _dwStartFall;
}

void CContra::EndFall()
{
	_dwStartFall = 0;
	_dwFallTime = 0;
}

#pragma endregion